/**
 * @file vue 2.0实现，类似vue 1.0的事件功能
 * 扩展vue对象$trigger方法, 触发eventHub中的事件
 * 组件的监听事件写在events里面
 *
 * @author fanxingguang@baidu.com
 * 2017-03-15
 */
import Vue from 'vue';

let hub = new Vue({});

/**
 * 判断是否空对象
 *
 * @param  {*}      obj  待检测值
 * @return {boolean}     返回值
 */
let isEmptyObject = function (obj) {
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            return false;
        }
    }
    return true;
};

/**
 * 处理Event，绑定或者解绑
 *
 * @param  {Object}  vm [Vue实例对象]
 * @param  {boolean} isOn   [是否绑定]
 */
let handleEvent = (vm, isOn) => {
    let events = vm.$options.events;
    if (isEmptyObject(events)) {
        return;
    }
    let action = isOn ? '$on' : '$off';
    for (let name in events) {
        if (events.hasOwnProperty(name)) {
            hub[action](name, events[name]);
        }
    }
};

export default {
    install(Vue) {
        // 全局注册一个混合，所有Vue对象在初始化的时候检测$options中的events
        // 然后created(创建)时在eventHub中注册事件，在组件beforeDestroy(注销前)解绑事件
        Vue.mixin({
            created() {
                let events = this.$options.events || {};
                for (let name in events) {
                    if (events.hasOwnProperty(name)) {
                        events[name] = events[name].bind(this);
                    }
                }
                handleEvent(this, true);
            },
            beforeDestroy() {
                handleEvent(this, false);
            }
        });

        /**
         * Vue全局触发事件
         *
         * @param {...*} args [参数列表]
         */
        Vue.prototype.$trigger = (...args) => {
            hub.$emit.apply(hub, args);
        };
    }
}